/**
 * Speichert alle Exemplare und Medien.
 * 
 * Alle Methoden mit setze...() weisen einer Variablen einen Wert zu.
 * Alle get...() Methoden liefern den Wert der jeweiligen Variablen
 * zurueck. Alle ...Hinzufuegen Methoden fuegen einen Wert einer Liste 
 * hinzu. Die ist....() pruefen ob ein Wert gesetzt ist und es wird
 * true oder false zurueck gegeben.
 * 
 * Datei: Mediumverwalter.java 	 	Autor: Simon Schindelmann 
 * Datum: 12.11.11                 	Version: 0.1
 * 
 * Historie:
 * 05.11.11:  v0.1    Klasse wurde angelegt.
 * 09.12.11   v0.2    platzFreigeben (EAN13) und pruefePlatz (Exemplar)
 *                    ertellt.
 * 
 */

package medienverwaltung;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import basis.ea.EA;
import medienverwaltung.simulation.Simulation;
import medienverwaltung.simulation.Uebersetzung;


public class Mediumverwalter
{
  private static HashMap<EAN13, Exemplar> exemplarListe 
  	= new HashMap<EAN13, Exemplar> ();
  private static ArrayList<Medium> medienListe
  	= new ArrayList<Medium> ();
  //Speichert die aktuelle Sprache die verwendet wird.
  private Uebersetzung uebersetzung = Uebersetzung.gibSprache ();
  private EA ea;

  
  /**
   * Wenn das Objekt erzeugt wird werden die Serialisierten Listen
   * geladen. (Nur bei der ersten Erzeugung des Objektes).   
   * @warning In dem Konstruktor sind Warnungen vorhanden, die nicht
   * entfernt werden koennen, da der Typ zur Laufzeit nicht
   * ueberprueft werden kann.
   */
  public Mediumverwalter () 
  {
    if(Simulation.istMedium () == false)
    {
      Simulation.setzeMedium (true);
      ea = new EA ("medienverwaltung.medium");
      if (ea.istGespeichertesXMLObjektVorhanden ())
      {
        medienListe = (ArrayList<Medium>) ea.einlesenXML ();
      }
      ea = new EA ("medienverwaltung.exemplar");
      if (ea.istGespeichertesXMLObjektVorhanden ())
      {
        exemplarListe = (HashMap<EAN13, Exemplar>) ea.einlesenXML ();
      }
    }
  }

  
  /**
   * Fuegt ein Medium der Medienliste hinzu.
   * @param m Medium das hinzugefuegt wird.
   */
  public void mediumHinzufuegen (Medium m)
  {
    medienListe.add (m);
  }


  /**
   * Liefert das Medium mit der gegebenen id zurueck.
   * @param MediumId wird uebergegeben
   * @return existiert ein Medium mit dieser ID wird das Medium zurueck
   * gegeben falls kein Medium zu dieser ID existiert wird Null zurueck
   * gegeben.
   */
  public Medium gibMedium (int id)
  {
    for (Medium m : medienListe)
    {
      if (m.gibMediumId () == id)
      {
        return m;
      }
    }
    return null;
  }
  
  
  /**
   * Gibt die Liste mit allen Medien zurueck.
   * @return ArrayListe mit allen Medien.
   */
  public ArrayList<Medium> gibMedienListe ()
  {
    return medienListe;
  }


  /**
   * Prueft ob ein Exemplar mit dieser EAN vorhanden ist.
   * @param ean EAN zu der geprueft werden soll ob ein Exemplar 
   * vorhanden ist.
   * @return Es wird true zurueck gegeben wenn ein Exemplar vorhanden
   * ist. Andernfalls false.
   */
  public boolean istVorhanden (EAN13 ean)
  {
    return exemplarListe.containsKey (ean);
  }


  /**
   * Gibt das Exemplar mit der entsprechenden EAN zureuck.
   * @param ean EAN des Exemplars das zurueck gegeben werden soll.
   * @return Exemplar mit der entsprechenden EAN.
   */
  public Exemplar gibExemplar (EAN13 ean)
  {
    return exemplarListe.get (ean);
  }

  
  /**
   * Gibt die Anzahl der Exemplare zurueck.
   * @return Anzahl der Exemplare.
   */
  public int anzahlExemplare ()
  {
    return exemplarListe.size ();
  }


  /**
   * Fuegt der Exemplar Liste ein Exemplar hinzu.
   * 
   * @param regalid ID des Regals wo das Exemplar stehen soll.
   * @param etage Regaletage in der das Exemplar stehen soll.
   * @param abschnitt Regalabschintt in dem das Exemplar stehen soll.
   * @param s Standort an welchen Standort das Exemplar zu finden ist.
   * @param m das Medium das eigentliche Exemplar.
   */
  public void exemplarHinzufuegen ( int sId,  Medium m, int regalid, 
      int etage, int abschnitt) throws MediumIstZuGross
  {
    Exemplar neu = new Exemplar (sId, m, regalid, etage, abschnitt);
    pruefePlatz (neu);
    exemplarListe.put (neu.gibBarcode (), neu);
  }


  /**
   * Fuegt ein Exemplar der Exemplar Liste hinzu
   * @param e das Exemplar das der List hinzugefuegt wird.
   * @MediumIstZuGross Wird geworfen wenn das Medium zu gross ist.
   */
  public void exemplarHinzufuegen (Exemplar e) throws MediumIstZuGross
  {
    pruefePlatz (e);
    exemplarListe.put (e.gibBarcode (), e);
  }


  /**
   * Gibt die Exemplarliste zuruck mit der Zuordnung EAN13 zu Exemplar.
   * @return HashMap mit allen EANs und Exemplaren.
   */
  public HashMap<EAN13, Exemplar> gibExemplarListe ()
  {
    return exemplarListe;
  }

  
  /**
   * Loescht das Exemplar mit der entsprechenden EAN.
   * @param ean EAN des Exemplars das geloescht werden soll.
   */
  public void exemplarLoeschen (EAN13 ean)
  {
    platzFreigeben (ean);
    exemplarListe.remove (ean);
  }

  
  /**
   * Speichert die Listen.
   */
  public void zustandSpeichern ()
  {
    try 
    { 
      ea = new EA ("medienverwaltung.medium"); 
      ea.speichernXML (medienListe); 
      ea = new EA ("medienverwaltung.exemplar"); 
      ea.speichernXML (exemplarListe); 
    } 
    catch (IOException e) 
    { 
      e.printStackTrace (); 
    }
  }


  /**
   * Es wird ueberprueft ob das Exemplar ueberhaupt ins Regal passt und
   * dann wird noch ueberprueft ob der Platz in diesen Abschnitt noch
   * fuer das Buch reicht, da schon andere Exemplare in den Abschitt
   * stehen koennen.
   * @param e das Exemplar was in den Abschnitt gestellt werden soll.
   */
  private void pruefePlatz (Exemplar e) throws MediumIstZuGross
  {
    Exemplar ex = e;
    Abmessung exa = ex.gibMedium ().gibAbmessung ();
    Regalabschnitt ab = ex.gibStandort ().gibRegal (ex.gibRegalId ())
        .gibRegaletage (ex.gibEtage ()).gibAbschnitt (
            ex.gibAbschnitt ());
    Abmessung abschnitt = ab.gibMessung ();
    int platzneu;

    if (exa.gibBreite () > abschnitt.gibLaenge ())
    {
      throw new MediumIstZuGross (uebersetzung.lokal
          .gibUebersetzung ("Medium ist zu Breit"));
    }
    else if (exa.gibHoehe () > abschnitt.gibHoehe ())
    {
      throw new MediumIstZuGross (uebersetzung.lokal
          .gibUebersetzung ("Medium ist zu hoch"));
    }
    else if (exa.gibLaenge () > abschnitt.gibBreite ())
    {
      throw new MediumIstZuGross (uebersetzung.lokal
          .gibUebersetzung ("Medium ist zu lang"));
    }
    else if (exa.gibBreite () > ab.gibPlatz ())
    {
      throw new MediumIstZuGross (uebersetzung.lokal
          .gibUebersetzung ("Nicht genug Platz im Abschnitt") + "\n" 
          + uebersetzung.lokal.gibUebersetzung ("Platz: ") + ab
          .gibPlatz () + " mm");
    }
    else
    {
      platzneu = ab.gibPlatz () - exa.gibBreite ();
      ab.setzePlatz (platzneu);
    }
  }


  /**
   * Diese Mothde wird aufgerufen wenn ein Exemplar aus den jeweiligen
   * Abschnitt geloescht wird
   * @param ean Die Ean nummer des Exemplars das geloescht wird.
   */
  private void platzFreigeben (EAN13 ean)
  {
    Exemplar ex;
    Abmessung exa;
    Regalabschnitt ab;
    int platzneu;
    
    ex = gibExemplar (ean);
    exa = ex.gibMedium ().gibAbmessung ();
    ab = ex.gibStandort ().gibRegal (ex.gibRegalId ())
        .gibRegaletage (ex.gibEtage ()).gibAbschnitt (ex
        .gibAbschnitt ());
    platzneu = ab.gibPlatz () + exa.gibBreite ();
    ab.setzePlatz (platzneu);
  }
  
  
  /**
   * Gibt die groesse des ExemplarListe zurueck.
   * @return
   */
  public int gibgroesse ()
  {
    return exemplarListe.size ();
  }
}
